package jenkins

import (
	"encoding/base64"
	"errors"
	"fmt"
	"gitee.com/laofa1/play/k_conf_mng/kconf_backend/pkg/setting"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)

type JobCreateParam struct {
	EnvName string
	JobName string
	Config io.Reader
}

func CreateViewJob(jobCreateParam JobCreateParam) error {
	if err := CreateJob(jobCreateParam); err != nil {
		log.Println(err)
		return err
	}

	if err := AddJobToView(jobCreateParam); err != nil {
		log.Println(err)
		return err
	}
	return nil
}

func CreateJob(jobCreateParam JobCreateParam) error {
	basicAuth := base64.StdEncoding.EncodeToString([]byte(setting.JenkinsUser + ":" + setting.JenkinsPassword))

	// get crumb
	crumb, err := GetCrumb(basicAuth)
	if err != nil {
		log.Println(err)
		return err
	}

	uri := setting.JenkinsApiBase + "/createItem?name=" + jobCreateParam.JobName
	req, err := http.NewRequest("POST", uri, jobCreateParam.Config)
	if err != nil {
		log.Println(err)
		return err
	}
	req.Header.Add("Authorization", "Basic " + basicAuth)
	req.Header.Add("Content-Type", "application/xml")
	req.Header.Add(crumb.CrumbRequestField, crumb.Crumb)
	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp, err := client.Do(req)
	if err != nil {
		log.Println(err)
		return err
	}
	defer func() {
		if err := resp.Body.Close(); err != nil {
			log.Println(err)
		}
	}()

	if resp.StatusCode != 200 {
		errMsg := fmt.Sprintf(
			"return code is not 200 from jenkins when create job: %s, code: %d",
			jobCreateParam.JobName,
			resp.StatusCode,
			)
		log.Println(errMsg)
		bodyErr, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Println(err)
			return err
		}
		log.Println(string(bodyErr))
		return errors.New(errMsg)
	}
	return nil
}

func AddJobToView(jobCreateParam JobCreateParam) error {
	basicAuth := base64.StdEncoding.EncodeToString([]byte(setting.JenkinsUser + ":" + setting.JenkinsPassword))

	uri := fmt.Sprintf(
		"%s/view/%s/addJobToView?name=%s",
		setting.JenkinsApiBase,
		jobCreateParam.EnvName,
		jobCreateParam.JobName,
		)
	req, err := http.NewRequest("POST", uri, nil)
	if err != nil {
		log.Println(err)
		return err
	}
	req.Header.Set("Authorization", "Basic " + basicAuth)
	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp, err := client.Do(req)
	if err != nil {
		log.Println(err)
		return err
	}
	if resp.StatusCode != 200 {
		errMsg := fmt.Sprintf("return code is not 200 from jenkins when add job: %s to view: %s",
			jobCreateParam.JobName, jobCreateParam.EnvName)
		return errors.New(errMsg)
	}
	return nil
}

func DeleteJob(jobName string) error {
	if jobName == "" {
		errMsg := "blank jobName"
		log.Println(errMsg)
		return errors.New(errMsg)
	}
	basicAuth := base64.StdEncoding.EncodeToString([]byte(setting.JenkinsUser + ":" + setting.JenkinsPassword))
	uri := setting.JenkinsApiBase + "/job/" + jobName + "/"
	req, err := http.NewRequest("DELETE", uri, nil)
	if err != nil {
		log.Println(err)
		return err
	}
	req.Header.Set("Authorization", "Basic " + basicAuth)
	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp, err := client.Do(req)
	if err != nil {
		log.Println(err)
		return err
	}
	if resp.StatusCode == 404 {
		return nil
	} else if resp.StatusCode != 200 && resp.StatusCode != 204 && resp.StatusCode != 302 {
		errMsg := fmt.Sprintf("return code is: %d from jenkins when detele job: %s",	resp.StatusCode, jobName)
		return errors.New(errMsg)
	}
	return nil
}

